import socket
import threading
import json
import pygame
import time
import xbox_controller

clients = {}

class client(object):
    def __init__(self, socket, addr, username):
        self.addr = addr[0]
        self.port = addr[1]
        self.username = username
        self.socket = socket
    
    def send(self, msg):
        self.socket.send(msg)
    
    def recv(self, mtu=1024):
        try:
            data = self.socket.recv(mtu)
            if not data:
                return False
            return data
        except:
            return False
    
    def close(self):
        try:
            self.socket.close()
            return True
        except:
            return False

    def id(self):
        return '{0}:{1}'.format(self.addr, self.port)


def control():
    global clients
    pygame.init()
    controller = xbox_controller.Controller()
    playing = False
    while True:
        time.sleep(0.002)
        # event handling
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                break

            if event.type == pygame.JOYBUTTONDOWN:
                # handle events for all controllers
                if not playing:
                    if event.button == xbox_controller.START: playing = True
                    else: continue
                else:
                    if event.button == xbox_controller.BACK: playing = False

                if event.button == xbox_controller.LEFT_BUMP:
                    print('LB down')

                if event.button == xbox_controller.RIGHT_BUMP:
                    print('RB down')

            elif event.type == pygame.JOYBUTTONUP:
                if not playing: continue
                if event.button == xbox_controller.LEFT_BUMP:
                    print('LB up')

                if event.button == xbox_controller.RIGHT_BUMP:
                    print('RB up')

            elif event.type == pygame.JOYHATMOTION:
                if not playing: continue
                pad_up, pad_right, pad_down, pad_left = controller.get_pad()
                pass

        # handle joysticks
        left_x, left_y   = controller.get_left_stick()
        right_x, right_y = controller.get_right_stick()
        forwardSpeed = left_y * 0.5
        sideSpeed = left_x * 0.5
        rotateSpeed = right_x *0.5

        if playing:
            data = [forwardSpeed, sideSpeed, rotateSpeed]
        else:
            data = [0.0, 0.0, 0.0, 0.0]
        data = json.dumps(data)
        for i in clients.values():
            i.socket.send(bytes(data.encode('utf-8')))
        
        # clock.tick(FPS)

def new_client(c):
    try:
        while True:
            data = c.recv()
            if not data:
                break
            else:
                pass
    except socket.error as e:
        print('({0})Socket error: {1}'.format(c.id(), e))
    except Exception as e:
        print('({0})Other exception: {1}'.format(c.id(), e))
    finally:
        print('({0})Client leave.'.format(c.id()))
        c.close()
        clients.pop(c.id())


threading.Thread(target=control).start()
# while True: pass

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
address = ('192.168.31.73', 8050) # localhost
s.bind(address)
s.listen(16)
print('Listening...')

while True:
    conn, addr = s.accept()
    c = client(conn, addr, '')
    clients[c.id()] = c
    threading.Thread(target=new_client, args=(c,)).start()
    print('({0})Client entry.'.format(c.id()))
